import get from 'lodash-es/get.js';
import last from 'lodash-es/last.js';
import isEmpty from 'lodash-es/isEmpty.js';
import Modal from 'ant-design-vue/es/modal/index.js';
import { hasToken, setToken } from '../utils/token';
import { setDocumentTitle } from '../utils/domUtils.js';
import { encryptRoute } from '../components/encrypt-route/index.js';
import { openPopupRoute } from '../components/popup-route/index.js';
import { getFirstValidMenuPath, useMenuStore } from '../pinia/menu.js';
import { Dialog } from '../components/antd-dialog/index.js';
import { useUserInfoStore } from '../pinia/userInfo.js';
import { useStaticDataStore } from '../pinia/staticData.js';
import { useSideMenuStore } from '../pinia/sideMenu.js';
import vueGlobal from '../vueGlobal.js';
import NProgress from '../plugins/NProgress.js';
import env from '../env.js';
import { logout, setStoreBackUrl } from '../views/login/utils.js';
import { openLogin } from '../api/index.js';

const config = {
  permissionChecker: () => true,
};

export function go(data) {
  if (!data || isEmpty(data)) return;
  const $router = vueGlobal.get('$router');
  const is_blank = get(data, 'is_blank');
  const path = get(data, 'path');
  if (get(data, 'is_nest_thirdparty_url')) {
    const thirdparty_url = get(data, 'thirdparty_url');
    if (is_blank) {
      window.open(thirdparty_url);
    } else {
      $router.push({ name: 'thirdparty', query: { url: encodeURIComponent(thirdparty_url) } });
    }
    return;
  }
  if (is_blank) {
    // window.open((env.BASE_URL + path).replace(/\/\//g, '/'));
    window.open(path);
    return;
  }
  if (path) {
    $router.push(path);
  }
}

export function isPathHasPermission(to) {
  return config.permissionChecker(to);
}

export function usePageTitleSetter(to, from, next) {
  const title = get(to, 'meta.title');
  if (title !== undefined) {
    setDocumentTitle(title);
  }
}

export async function useNoMatchRouteCheck(to, from, next) {
  return await new Promise((resolve, reject) => {
    if (!to || !to.matched || !to.matched.length) {
      vueGlobal.get('$message').warn('当前页面建设中,敬请期待~');
      return reject('NoMatchRoute: ' + to.fullPath);
    }
    resolve();
  });
}

export async function useAutoLogin(to, from, next) {
  return await new Promise(async (resolve, reject) => {
    const query = get(to, 'query') || {};
    const login_security_code = get(query, 'login_security_code');
    if (login_security_code) {
      // 先把存储信息清空 - 平台之间相互跳转出现问题
      logout(false);
      const res = await openLogin({ login_security_code }).catch(() => ({}));
      const data = res ? res.data || {} : {};
      // 先判断角色类型 后台or投屏 role_type（1：后台  2：投屏）
      // 再判断一下是否有免登录权限
      const role_type = data.role_type;
      if (String(role_type == 2 ? res.data.user.no_login_gis : res.data.user.no_login_ht).trim() === '0') {
        logout(true);
        return resolve();
      }
      if (data.access_token) {
        setToken(data.access_token);
        // 去掉免登录地址参数
        vueGlobal.get('$router').replace({
          path: to.path,
          query: Object.keys(query).reduce((res, key) => {
            return key === 'login_security_code' ? res : Object.assign(res, { [key]: query[key] });
          }, {}),
        });
        next(false);
        return reject('AutoLogin success and reroute');
      } else {
        await vueGlobal.get('$message').loading('自动登录失败,即将跳转到登录！', 5);
        logout(true);
        return reject('AutoLogin fail and go to login');
      }
    }
    return resolve();
  });
}
// 存储返回地址
export async function useStoreBackUrl(to, from, next) {
  return await new Promise(async (resolve, reject) => {
    const query = get(to, 'query') || {};
    // cyBackUrl: backUrl 为诚运平台返回地址
    // selfBackUrl 为自己平台返回地址
    const cyBackUrl = get(query, 'backUrl', '');
    const selfBackUrl = get(query, 'selfBackUrl', '');
    setStoreBackUrl(cyBackUrl, selfBackUrl);
    return resolve();
  });
}

export async function useSameRoutePathCheck(to, from, next, key) {
  return await new Promise((resolve, reject) => {
    key = key || 'fullPath';
    if (to[key] !== '/' && to[key] === from[key]) {
      next(false);
      return reject('SameRoutePath ' + to[key] + ' ' + from[key]);
    }
    return resolve();
  });
}

export async function useCheckToken(to, from, next) {
  return await new Promise((resolve, reject) => {
    if (get(to, 'meta.checkToken') === false) {
      next();
      return reject('not need token: ' + to.fullPath);
    }
    if (!hasToken()) {
      logout(true);
      return reject('no token and go to login: ' + to.fullPath);
    }
    return resolve();
  });
}

export async function useUserInfoGetter(to, from, next) {
  return await new Promise(async (resolve, reject) => {
    const userInfoStore = useUserInfoStore();
    await userInfoStore.getUserInfoAsync().catch(() => {
      logout(true);
      reject('useUserInfoGetter: getUserInfoAsync error');
    });
    resolve();
  });
}

export async function useUserMenusGetter(to, from, next) {
  return await new Promise(async (resolve, reject) => {
    const menuStore = useMenuStore();
    config.permissionChecker = menuStore.isPathHasPermission;
    await menuStore.getMenuAsync().catch(() => {
      vueGlobal.get('$message').error('获取菜单失败，请刷新页面再次尝试！');
    });
    if (to.path === '/') {
      const firstValidPath = getFirstValidMenuPath(menuStore.menus);
      if (firstValidPath) {
        next({ path: firstValidPath });
        return reject();
      }
    }
    resolve();
  });
}

export async function useUserSideMenusGetter(to, from, next) {
  return await new Promise(async (resolve, reject) => {
    const sideMenuStore = useSideMenuStore();
    config.permissionChecker = sideMenuStore.isPathHasPermission;
    await sideMenuStore.getMenuAsync().catch(() => {
      vueGlobal.get('$message').error('获取菜单失败，请刷新页面再次尝试！');
    });
    resolve();
  });
}

export async function useUserButtonsGetter(to, from, next) {
  return await new Promise(async (resolve, reject) => {
    const userInfoStore = useUserInfoStore();
    await userInfoStore.getUserButtonsAsync().catch(() => {
      vueGlobal.get('$message').error('获取按钮权限失败，请刷新页面再次尝试！');
    });
    resolve();
  });
}

export async function useStaticDataGetter(to, from, next) {
  return await new Promise(async (resolve, reject) => {
    const userInfoStore = useUserInfoStore();
    const staticDataStore = useStaticDataStore();
    await staticDataStore.getStaticDataAsync(userInfoStore.area_code).catch(() => {
      return reject('get Static Data error');
    });
    resolve();
  });
}

export async function useRoutePermissionCheck(to, from, next) {
  return await new Promise((resolve, reject) => {
    if (!isPathHasPermission(to)) {
      vueGlobal.get('$message').warn('无权访问该页面，如若需要请联系管理员！');
      next(false);
      return reject('Route ' + to.fullPath + ' has no Permission');
    }
    resolve();
  });
}

export async function useRoutePasswordCheck(to, from, next) {
  return await new Promise(async (resolve, reject) => {
    /* 页面是否需要密码 */
    const menuStore = useMenuStore();
    const { routerKeyEnum } = menuStore;
    const isNeedPwd = menuStore.getMenuData(routerKeyEnum[to.path], 'is_password_auth');
    if (isNeedPwd) {
      await encryptRoute().catch(() => reject('route password error'));
    }
    resolve();
  });
}

export async function usePopupRouteCheck(to, from, next) {
  return await new Promise(async (resolve, reject) => {
    /* 页面是否使用弹窗方式展示 */
    const menuStore = useMenuStore();
    const isPopup = menuStore.getMenuData(to.path, 'is_popup');
    if (isPopup) {
      const title = menuStore.getMenuData(to.path, 'title');
      const matched = last(get(to, 'matched') || []);
      openPopupRoute(title, get(matched, 'components.default'));
      next(false);
      return reject('route page is viewed as a popup');
    }
    resolve();
  });
}

export async function useMicroEnvCheck(to, from, next) {
  return new Promise((resolve, reject) => {
    const micro_env = get(to, 'query.micro_env');
    if (micro_env === '1') {
      window.__MICRO_ENV_ = true;
      return resolve();
    }
    if (window.__MICRO_ENV_ === true) {
      to.query.micro_env = '1';
      next(to);
      return reject();
    }
    return resolve();
  });
}

export async function useRouteProgress(to, from, next, hook) {
  try {
    NProgress.start();
    if (typeof hook === 'function') {
      await hook(to, from, next);
    }
    next();
    NProgress.done();
  } catch (error) {
    console.log(error);
    NProgress.done();
  }
}

export async function useRouteFinish(to, from) {
  Dialog.destroyAll();
  Modal.destroyAll();
  NProgress.done();
}

export async function useRouterOnError(error, to, from) {
  NProgress.done();
}

export async function useRouterAfterEach(to, from) {
  useRouteFinish(to, from).catch();
}

export async function useRouterBeforeEach(to, from, next) {
  await useRouteProgress(to, from, next, async (to, from, next) => {
    await useNoMatchRouteCheck(to, from, next);
    await useSameRoutePathCheck(to, from, next);
    await usePageTitleSetter(to, from, next);
    await useAutoLogin(to, from, next);
    await useStoreBackUrl(to, from, next);
    await useCheckToken(to, from, next);
    await useUserInfoGetter(to, from, next);
    await useUserMenusGetter(to, from, next);
    await useRoutePermissionCheck(to, from, next);
    await useRoutePasswordCheck(to, from, next);
    await usePopupRouteCheck(to, from, next);
    useStaticDataGetter(to, from).catch((error) => error);
  });
}

export async function useRouterBeforeEachForAdmin(to, from, next) {
  await useRouteProgress(to, from, next, async (to, from, next) => {
    await useNoMatchRouteCheck(to, from, next);
    await useSameRoutePathCheck(to, from, next);
    await usePageTitleSetter(to, from, next);
    await useAutoLogin(to, from, next);
    await useCheckToken(to, from, next);
    await useUserInfoGetter(to, from, next);
    await useUserSideMenusGetter(to, from, next);
    await useRoutePermissionCheck(to, from, next);
    useUserButtonsGetter(to, from).catch((error) => error);
  });
}
